package connection;

import com.franz.ag.*;
import datamodel.Author;
import datamodel.MetaInfo;
import org.jdom.CDATA;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.Namespace;
import org.jdom.output.Format;
import org.jdom.output.XMLOutputter;

import java.io.IOException;
import java.util.HashMap;

import example.jaxws.NewIDGener;

public class AGConnecting {

    static AllegroGraphConnection ags = new AllegroGraphConnection();
    static AllegroGraph ts;
    static Document document = new Document();
    static HashMap<String, MetaInfo> resultMap;
    static CDATA queryElement;
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // this method is only for test
    public static void main(String[] args) throws AllegroGraphException {
        Element root = new Element("Documents");

        Namespace msns = Namespace.getNamespace("b", "http://schemas.microsoft.com/office/word/2004/10/bibliography");
        connect();
        doSparqlSelectMetaInfoNoXML("Aspirin");

        System.out.println(resultMap.size());
        for (String key : resultMap.keySet()) {
            doSparqlSelectAuthor(key);
            root.addContent(resultMap.get(key).toXMLElement(msns));
        }
        disconnect();
       document.setRootElement(root);
       root.addContent(new Element("Query").addContent(queryElement));
       writeXML();
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // here begin the search process
    public static Document runSearch(String drugName) throws AllegroGraphException {
        Element root = new Element("Documents");

        Namespace msns = Namespace.getNamespace("b", "http://schemas.microsoft.com/office/word/2004/10/bibliography");
        connect();

        // load SPARQL
        if( drugName.equalsIgnoreCase("telmisartan ramipril")) {
             doSparqlSelectMetaInfoNoXML("telmisartan", "ramipril");
        }
        else if( drugName.equalsIgnoreCase("clopidogrel aspirin")) {
             doSparqlSelectMetaInfoNoXML("clopidogrel", "aspirin");
        }
        else {
            doSparqlSelectMetaInfoNoXML(drugName);
        }

        // System.out.println(resultMap.size());    // test code
        for (String key : resultMap.keySet()) {
            doSparqlSelectAuthor(key);
            root.addContent(resultMap.get(key).toXMLElement(msns));
        }
        disconnect();
        document.setRootElement(root);
        root.addContent(new Element("Query").addContent(queryElement));
        return document;
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // JDom create meta-information
    private static void writeXML() {
        Format fmt = Format.getPrettyFormat();
        fmt.setIndent("  ");

        XMLOutputter outputter = new XMLOutputter();
        outputter.setFormat(fmt);
        try {
            outputter.output(document, System.out);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static void connect() throws AllegroGraphException {
        try {
            // This example connects to a server on the default port.
            // For servers listening on a non-default port, e.g. 4126,
            // uncomment this to specify the port:
            //ags.setPort(4126);
            System.out.println("Attempting to connect to the server on port " + ags.getPort());
            ags.enable();
        } catch (Exception e) {
            throw new AllegroGraphException("Server connection problem -- please ensure the server is running.", e);
        }
        System.out.println("Connection enabled.");

        // Open a store -- default is read-write access
        System.out.println("Open: open an existing store, error otherwise.");
        ts = ags.open("obit-interpretated-ts", AGPaths.TRIPLE_STORES );
        System.out.println("Triple store opened with " + ts.numberOfTriples() + " triples.");
    }

    private static void disconnect() throws AllegroGraphException {
        // Close the triple store
        ts.closeTripleStore(true);
        // Disconnect from the server
        System.out.println("Disconnecting from the server.");
        ags.disable();
        System.out.println("Done.");
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // select document metainfo from Tripel Store with the Name of Drug.
    public static void doSparqlSelectMetaInfoNoXML(String drugName) throws AllegroGraphException{
        String query = Querise.qMetaInfoNoAuthorPerDrug(drugName);

        SPARQLQuery sq = new SPARQLQuery();
        sq.setTripleStore(ts);
        sq.setQuery(query);

        resultMap = new HashMap<String, MetaInfo>();

        System.out.println("  " + sq.getQuery());
        queryElement = new CDATA(sq.getQuery());

        ValueObject[][] r = sq.select();
        String[] var = sq.getResultNames();
        System.out.println("Number of solutions: " + r.length);

        for (int i = 0; i < r.length; i++) {
            ValueObject[] objects = r[i];
            System.out.println("Solution " + (i+1) + ":");
            MetaInfo aMetaInfo = new MetaInfo();

            for (int j = 0; j < objects.length; j++) {
                ValueObject term = objects[j];
                String value = AGUtils.printValueObject(term);
                System.out.println("  " + var[j] + " = " + AGUtils.printValueObject(term));
                aMetaInfo.setFieldData(j, value);
            }
            aMetaInfo.setTag(aMetaInfo.getSourceType() + NewIDGener.newId("tagid"));

            resultMap.put(aMetaInfo.getSourceURL(), aMetaInfo);
        }

    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // select document metainfo from Tripel Store with the Name of Drug.
    public static void doSparqlSelectMetaInfoNoXML(String drugName1, String drugName2) throws AllegroGraphException{
        String query = Querise.qMetaInfoNoAuthorPerDrugCombi(drugName1, drugName2);

        SPARQLQuery sq = new SPARQLQuery();
        sq.setTripleStore(ts);
        sq.setQuery(query);

        resultMap = new HashMap<String, MetaInfo>();

        System.out.println("  " + sq.getQuery());                  // test code
        queryElement = new CDATA(sq.getQuery());

        ValueObject[][] r = sq.select();
        String[] var = sq.getResultNames();
        System.out.println("Number of solutions: " + r.length);    // test code

        for (int i = 0; i < r.length; i++) {
            ValueObject[] objects = r[i];
            System.out.println("Solution " + (i+1) + ":");
            MetaInfo aMetaInfo = new MetaInfo();

            for (int j = 0; j < objects.length; j++) {
                ValueObject term = objects[j];
                String value = AGUtils.printValueObject(term);
                System.out.println("  " + var[j] + " = " + AGUtils.printValueObject(term));
                aMetaInfo.setFieldData(j, value);
            }
            aMetaInfo.setTag(aMetaInfo.getSourceType() + NewIDGener.newId("tagid"));

            resultMap.put(aMetaInfo.getSourceURL(), aMetaInfo);
        }

    }

    // automatic select the Authorlist form the TS with sourceURL
    private static void doSparqlSelectAuthor( String keySourceURL) throws AllegroGraphException{
        String query = Querise.getAuthorsProDoc(keySourceURL);
        SPARQLQuery sq = new SPARQLQuery();
        sq.setTripleStore(ts);
        sq.setQuery(query);

        System.out.println("  " + sq.getQuery());                   // test code

        ValueObject[][] r = sq.select();
        String[] var = sq.getResultNames();
        System.out.println("Number of solutions: " + r.length);     // test code

        for (int i = 0; i < r.length; i++) {
            Element sourceElement = new Element("Source");
            ValueObject[] objects = r[i];
            System.out.println("Solution " + (i+1) + ":");          // test code
            Author aAuthor = new Author();

            for (int j = 0; j < objects.length; j++) {
                ValueObject term = objects[j];
                sourceElement.addContent(new Element(var[j]).setText(AGUtils.printValueObject(term)));
                System.out.println("  " + var[j] + " = " + AGUtils.printValueObject(term));
                aAuthor.setFieldData(j, AGUtils.printValueObject(term));
            }
            resultMap.get(keySourceURL).getAuthorList().add(aAuthor);
            System.out.println(aAuthor);                            // test code
        }

    }
}
